import javax.swing.*;
import java.io.*;
import java.util.*;

public class Player implements Entity, Serializable {
	
	public enum Status {HOSTILE, UNFRIENDLY, NEUTRAL, FRIENDLY, HONOURED, INANIMATE, CORPSE }
	
	Random random = new Random();
	
	private int Endurance;
	private int Strength;
	private int Intelligence;
	private int Agility;
	private int Willpower;
	private int maxHP;
	private int currentHP;
	private int skillPoints;
	
	private int Gold;
	
	private int AxeSkill;
	private int SwordSkill;
	private int DaggerSkill;
	private int MaceSkill;
	private int MaulSkill;
	private int GreatAxeSkill;
	private int GreatSwordSkill;
	private int UnarmedSkill;
	
	private double Weight;
	
	private int ActionsPerformed;
	private int lastSlept;
	
	private Character conversationPartner;
	
	private GUI gui;
	
	private double actionPoints;
	private double maxAP;
	
	private ArrayList<Ability> Abilities = new ArrayList<Ability>();
	private ArrayList<StatusEffect> statuseffects = new ArrayList<StatusEffect>();
	private ArrayList<Quest> QuestLog = new ArrayList<Quest>();
	
	protected boolean isBed = false;
	protected boolean isCorpse;
	private boolean forSale = false;
	protected String DisplayName;
	protected String Name;
	protected String Description;
	protected String Orientation;
	protected String charName;
	private Status status;
	protected ArrayList<Entity> Inventory = new ArrayList<Entity>();
	protected boolean CanBePickedUp = false;
	protected String Why;
	private Location location;
	private boolean isVisible;
	private Item toomany = new Item("toomany", "toomany", "toomany", "toomany", 0);
	private int value;
	
	private Character currentOpponent;
	
	private Weapon Main_Hand;
	private Weapon Off_Hand;
	private Armour Head;
	private Armour Shoulders;
	private Armour Chest;
	private Armour Hands;
	private Armour Legs;
	private Armour Feet;
	
	private double ArmourRating;
	
	private boolean inCombat;
	private boolean isAsleep;
	
	
	public Player() {
		GenStats();
		maxHP = Endurance * 10;
		maxAP = Endurance * 4;
		currentHP = maxHP;
		isVisible = true;
		Weight = 70.0;
		isCorpse = false;
		inCombat = false;
		isAsleep = false;
		skillPoints = 0;
		ActionsPerformed = 0;
		Gold = 0;
		addAbility(new Ability(-10.000000, -10, 1, "Attack"));
		Main_Hand = new Weapon("", "crude", "bone", "fists");
	}
	
	public void addAbility(Ability a) {
		Abilities.add(a);
	}
	
	public void modifyGold(int a) {
		Gold = Gold + a;
		gui.getFeedbackWindow().append("Your gold has been modified by " + a + "\n");
	}
	
	public int getGold() {
		return Gold;
	}
	
	public double getMaxAP() {
		return maxAP;
	}
	
	public double getWeight() {
		return Weight;
	}
	
	public void Put(Entity a, Entity b, String c, JTextArea y) {
			if (b.isLocked() == false) {
				a.setOrientation(c);
				b.addEntity(a);
				Inventory.remove(a);
				y.append("You put the " + a.getName() + " " + a.getOrientation().toLowerCase() + " the " + b.getName() + ".");
			} else {
				y.append("The " + b.getName() + " is locked!");
			}
	}

	public void Examine(String a, JTextArea y) {
		Entity target = (location.findObject(a));
		if (target.getName().equalsIgnoreCase("toomany")) {
			y.append("You can see more than one object with that description, please be more specific." + "\n");
		} else {
				target.Describe(y);
		}
	}
	
	public void ExamineSpecific(Entity a, JTextArea y) {
		
		if (a.getName().equalsIgnoreCase("toomany")) {
			y.append("There is more than one object matching that description, please be more specific." + "\n");
		} else {
		a.Describe(y);
		}
	}
	
	public void Buy(Entity a, Character b, JTextArea y) {
		if (Gold >= a.getValue()) {
			Inventory.add(a);
			b.modifyGold(a.getValue());
			location.removeObject(a);
			y.append("You buy the " + a.getName() + " from " + b.getName() + " for " + a.getValue() + "g.\n");
			modifyGold(a.getValue() * -1);
		} else {
			y.append("You can't afford this! You need " + a.getValue() + "g and you currently have " + Gold + "g.\n");
		}
	}
	
	public void Sell(Entity a, Character b, JTextArea y) {
		if ((b.getGold() >= a.getValue()) && a.getValue() > 0) {
			b.addEntity(a);
			Inventory.remove(a);
			modifyGold(a.getValue());
			b.modifyGold(a.getValue() * -1);
			y.append("You sell the " + a.getName() + " to " + b.getName() + " for " + a.getValue() + "g.\n");
		} else if (b.getGold() < a.getValue()){
			y.append(b.getName() + " says: I'm sorry, I can't afford that at the moment! Let me shift some more stock and maybe I can afford it later.");
		} else if (a.getValue() <= 0) {
			y.append(b.getName() + " is not interested in buying " + a.getDisplayName());
		}
	}
	
	public void takeSpecific(Entity a, Entity b, JTextArea y) {
		
		if (a == null) {
			y.append("You can't see an object in that location." + "\n");
			
		} else {
		if (a.TestCanBePickedUp() == true) {
			if (a.getWeight() > availableSpace()) {
				y.append("You're carrying too much already! Try discarding some items first, then try again.");
			} else {
				Inventory.add(a);
				location.removeSpecificObject(a, b);
				y.append("You take the " + a.getName() + " and put it in your backpack." + "\n");
			}
		} else {
			y.append(a.CanBePickedUp_Why());
		}
	
		}
	}
	
	public void setLocation(Location a) {
		location = a;
	}
	
	public Location getCurrentLocation() {
		return location;
	}
	
	public void useItem(Entity a, String b, JTextArea y, JTextField x) {
		a.Use(this, b, y, x);
	}
	
	public void useExit(String a, JTextArea y, JTextArea x) {
		
		Exit exit = location.findExit(a);
		
		if (exit.isLocked() == false) {
		location = exit.getDestination();
		y.setText("");
		y.append("You head through the " + exit.getName() + "...\n\n");
		location.Display(x);
		} else {
			y.append("You attempt to go through the " + exit.getName() + ", but it is locked and won't budge." + "\n\n");
		}
	}
	
	public void isCorpse(boolean a) {
		isCorpse = a;
	}
	
	public Entity findItemInInventory(String a) {
		int counter = 0;
		Entity result = null;
		for (Entity b : Inventory) {
			if (b.getName().contains(a) || a.contains(b.getName())) {
				if (b.isVisible() == true) {
				result = b;
				counter++;
				}
			}
		}
		
		if (counter > 1) {
			return toomany;
		} else {
		return result;
		}
	}
	
	public void takeItem(String a, JTextArea y, InventoryWindow x) {
		
		Entity Found = location.findObject(a);
		
		if (Found.getName().equalsIgnoreCase("toomany")) {
			y.append("You can see more than one object fitting that description, please be more specific." + "\n");
		
		} else if ((Found.getClass().getName()) == "Exit" || (Found.getClass().getName()) == "StaticObject") {
			y.append("You cannot pick that up!" + "\n");
		} else if (Found.TestCanBePickedUp() == false) {
			y.append(Found.CanBePickedUp_Why() + "\n\n");
		} else if (Found.getWeight() > availableSpace()) {
			y.append("You're carrying too much already! Try discarding some items first, then try again.");
		} else {
		Inventory.add((location.findObject(a)));
		y.append("You take the " + Found.getName() + " and put it in your backpack." + "\n");
		x.Refresh(this);
		location.removeObject(a);
		}
	}
	
	public void modifyStrength(int a) {
		Strength = Strength + a;
		if (a != 0 ) {	
			gui.getFeedbackWindow().append("Your Strength has been");
			if (a > 0) {
				gui.getFeedbackWindow().append(" increased ");
			} else {
				gui.getFeedbackWindow().append(" decreased ");
			}
			gui.getFeedbackWindow().append("by " + Math.abs(a) + ".\n");
		}
	}
	
	public void modifyAgility(int a) {
		Agility = Agility + a;
		if (a != 0) {
		gui.getFeedbackWindow().append("Your Agility has been");
		if (a > 0) {
			gui.getFeedbackWindow().append(" increased ");
		} else {
			gui.getFeedbackWindow().append(" decreased ");
		}
		gui.getFeedbackWindow().append("by " + Math.abs(a) + ".\n");
		}
	}
	
	public void dropItem(String a, JTextArea y, InventoryWindow x) {
		
		try {
		if (findItemInInventory(a).getName().equalsIgnoreCase("toomany")) {
			y.append("You have more than one item matching that description, please be more specific.\n\n");
		} else {
			findItemInInventory(a).setOrientation("On the floor");
			getCurrentLocation().addEntity(findItemInInventory(a));
			Inventory.remove(findItemInInventory(a));
			x.Refresh(this);
			y.append("You drop the " + a + " on the floor.");
		}
		} catch (NullPointerException e) {
			if (Main_Hand.getDisplayName().contains(a) || a.contains(Main_Hand.getDisplayName())) {
				this.unequip(a);
				this.dropItem(a, y, x);
			} else {
			y.append("You don't have an item matching that description.\n\n");
			}
		}
	}
	
	public void giveQuestItem(Entity a, Character b) {
		b.addEntity(a);
		a.setVisible(false);
		Inventory.remove(a);
	}
	
	public void giveObject(String a, String b, JTextArea y, InventoryWindow x) {
		
		Character recipient = location.findCharacter(b);
		Entity item = findItemInInventory(a);
		
		if (recipient == null) {
			y.append("You can't see anyone matching that description.");
		} else if (recipient.getName().equalsIgnoreCase("toomany")) {
			y.append("There is more than one person in the room matching that description.");			
		} else {
		
		try {
			if (item.getName().equalsIgnoreCase("toomany")) {
				y.append("You have more than one item matching that description, please be more specific.\n\n");
			} else if (recipient.receiveObject(item) == true && recipient.isCorpse() == false){
				recipient.addEntity(item);
				item.setVisible(false);
				Inventory.remove(findItemInInventory(a));
				recipient.modifyDisposition(item.getValue());
				x.Refresh(this);
				y.append("You give the " + a + " to the " + recipient.getName() + ". ");
				y.append(recipient.getAcceptGiftResponse());
				} else if (recipient.receiveObject(item) == false) {
					y.append(recipient.getRejectGiftResponse() + ". ");
					if (item.getValue() < 0) {
						y.append(recipient.getName() + " is insulted by your offer!");
						recipient.modifyDisposition(item.getValue());
					}
				} else if (recipient.isCorpse() == true) {
					y.append("The " + recipient.getName() + " is dead!");
				}
			}catch (NullPointerException e) {
				y.append("You don't have an item matching that description.\n\n");
			}
		}
	}
	
	public int getValue() {
		return value;
	}
	
	public void setValue(int a) {
		value = a;
	}
	
	public void lootObject(String a, JTextArea y) {
		
		try {
			
			if (location.findObject(a).isLocked() == true) {
				y.append("You try to examine the contents of the " + location.findObject(a).getName() + " but it's locked.");
			} else {
			location.findObject(a).setContentsVisible(true);
			y.append("Searching the " + location.findObject(a).getName() + ", you find the following:\n\n");
			for (Entity b : location.findObject(a).getInventory()) {
				y.append(b.getDisplayName().substring(0, 1).toUpperCase() + b.getDisplayName().substring(1) + "\n");
			}
			if (Gold > 0) {
				y.append("You find " + location.findObject(a).getGold() + " gold.");
				modifyGold(location.findObject(a).getGold());
				location.findObject(a).setGold(0);
			}
			}
		} catch (NullPointerException e) {
			y.append("You can't see an object matching that description");
		}
		
		
	}
	
	public void setGold(int a) {
		Gold = a;
	}
	
	public void lootCharacter(String a, JTextArea y) {
		try {
			
			if (location.findCharacter(a).getStatus().toString().equalsIgnoreCase("CORPSE")) {
				location.findCharacter(a).setContentsVisible(true);
				y.append("Searching " + location.findCharacter(a).getDisplayName() + ", you find ");
				if (location.findCharacter(a).getInventory().size() == 0 && location.findCharacter(a).getGold() == 0) {
					y.append("nothing of interest.\n");
				} else {		
						y.append("the following:\n\n");
					for (Entity b : location.findCharacter(a).getInventory()) {
						y.append(b.getDisplayName().substring(0, 1).toUpperCase() + b.getDisplayName().substring(1) + "\n");
					}
					if (location.findCharacter(a).getGold() > 0) {
						y.append("You find " + location.findCharacter(a).getGold() + " gold\n");
						modifyGold(location.findCharacter(a).getGold());
						location.findCharacter(a).setGold(0);
					}		
				}

			} else {
				y.append("The " + location.findCharacter(a).getName() + " isn't dead yet!");
			}
			
		} catch (NullPointerException e) {
			y.append("You can't see an object matching that description");
		}	
	}
	
	public void printInventory(JTextArea y) {
		y.append("Searching the " + DisplayName + " you find the following items:\n\n");
		for (Entity a : Inventory) {
			y.append(a.getName().substring(0, 1).toUpperCase() + a.getName().substring(1) + "\n");
		}
	}
	
	public void speak(JTextArea y, Character a, String b, Player c) {
	if (a.getStatus().toString().equalsIgnoreCase("CORPSE")) {
		y.append(a.getName() + "'s corpse lies there silently.");
	} else {
		if (a.getDisposition() <= -300) {
			y.append(a.getName() + " scowls at you in silence. It's clear they have no interest in talking to you.");
		} else if (a.getDisposition() > -300 && a.canSpeak() == true){
			if (b.equalsIgnoreCase("Surroundings") || b.equalsIgnoreCase("location") || b.contains(location.getDisplayName()) || location.getDisplayName().contains(b) || location.getLocale().getName().contains(b)) {
					a.giveHistory("General History", this.location, y);
			} else if (b.equalsIgnoreCase("himself") || b.equalsIgnoreCase("themselves")){
				if (a.getDisposition() > 500) {
					if (random.nextInt(2) == 0) {
					a.giveHistory("General Personal", location, y);
					} else {
						a.giveHistory("Secret Personal", this.location, y);
					}
			} else {
				a.giveHistory("General Personal", this.location, y);
			}
		} else if (b.equalsIgnoreCase("secret") || b.equalsIgnoreCase("Secrets")) {
				if (a.getDisposition() < 500) {
					y.append("The " + a.getName() + " says: I don't think I trust you enough to talk about that.");
				} else {
						a.giveHistory("Secret History", this.location, y);
				}
		} else if (b.equalsIgnoreCase("quest") || b.equalsIgnoreCase("Quests")) {
			try {
			if (a.getNextQuest().checkComplete() == true) {
				a.getNextQuest().complete();
				if (a.getNextQuest().getMissionType().equalsIgnoreCase("has")) {	
					for (Entity p : a.getNextQuest().getQuestItems()) {
						y.append("You give " + p.getDisplayName().toLowerCase() + " to " + a.getName().toLowerCase() + ".\n");
					}
				} else if (a.getNextQuest().getMissionType().equalsIgnoreCase("kill")) {
					y.append("You inform " + a.getName() + " of the death of ");
					for (Entity p : a.getNextQuest().getQuestItems()) {
						y.append(p.getName() + " ");
					}
					y.append(".\n");
				}
				y.append(a.getNextQuest().getCompleteText() + "\n");
				y.append("Quest " + "'" + a.getNextQuest().getTitle() + "' complete!\n");
				y.append("You have been awarded " + a.getNextQuest().getXP_Reward() + " skill points.\n");
				for (Entity i : a.getNextQuest().getRewards()) {
					y.append("You receive " + i.getDisplayName() + ".\n");
				}
				a.getQuests().remove(0);
			} else if (a.getNextQuest().isGiven() == false){
				a.getNextQuest().give();
				y.append(a.getNextQuest().getQuestText());
				if (a.getNextQuest().getMissionType().equalsIgnoreCase("speak to")) {
					a.getQuests().remove(a.getNextQuest());
				}
				
			} else {
				
				y.append(a.getNextQuest().getImpatient());
			}
			} catch (IndexOutOfBoundsException e) {
				y.append(a.getName() + " says: Sorry, I have no tasks for you at this time.");
			}
		} else if (b.equalsIgnoreCase("Trade")) {
			if (a.isMerchant() == true && a.getLocation().isShop() == true) {
				y.append(a.getName() + " says: Please feel free to look around and examine my wares");
				if (a.countSaleItems() > 0) {
						y.append(". In addition to what you see here, I also have the following items for sale:\n\n");
						for (Entity item : a.getInventory()) {
							if (item.isForSale() == true) {
								y.append(item.getName() + "\n");
							}
						}
				} else {
					y.append(", what you see here is what I've got.");
				}
			} else if (a.isMerchant() == true && a.getLocation().isShop() == false) {
				y.append(a.getName() + " says: I do have a small selection of items you might like to buy:\n\n");
				for (Entity item : a.getInventory()) {
					if (item.isForSale() == true) {
						y.append(item.getName() + "\n");
					}
				}
			} else if (a.isMerchant() == false) {
				y.append(a.getName() + " says: I'm sorry, I have nothing to sell. You'll need to find a merchant or shopkeeper for that.");
			}
		} else {
			a.findTopic(b);
		}
		} else {
			y.append(a.getName() + " stares at you in silence.\n");
		}
	}
	}
	
	public void addEntity(Entity a) {
		Inventory.add(a);
	}
	
	public void addEntities(Entity ... entities) {
		for (Entity a : entities) {
		Inventory.add(a);
		gui.getFeedbackWindow().append("You receive " + a.getDisplayName() + ".\n");
		}
	}
	
	public void setMain_Hand(Weapon a) {
		Main_Hand = a;
	}
	
	public ArrayList<Entity> getInventory() {
		return Inventory;
	}
	
	public void removeObject(Entity a) {
		Inventory.remove(a);
	}
	
	public void Describe(JTextArea y) {
		y.append(Description + "." + "\n");	
	}
	
	
	public void Display(JTextArea y) {
		y.append(Orientation + " is " + DisplayName + ". ");
	}
	
	public String getOrientation() {
		return Orientation;
	}
	
	public void setOrientation(String a) {
		Orientation = a;
	}
	
	public String getDisplayName(){
		return DisplayName;
	}
	
	public String getName() {
		return Name;
	}
	
	public String getDescription() {
		return Description;
	}
	
	public void Use(Player a, String b, JTextArea y, JTextField x) {		
	}
	
	public boolean TestCanBePickedUp() {
		return CanBePickedUp;
	}
	
	public void CantBePickedUp(String b) {
		CanBePickedUp = false;
		Why = b;		
	}
	
	public String CanBePickedUp_Why() {
		return Why;
	}
	
	public int getEndurance() {
		return Endurance;
	}
	
	public int getStrength() {
		return Strength;
	}
	
	public int getIntelligence() {
		return Intelligence;
	}
	
	public int getAgility() {
		return Agility;
	}
	
	public int getWillpower() {
		return Willpower;
	}
	
	public int getMaxHP() {
		return maxHP;
	}
	
	public int getCurrentHP() {
		return currentHP;
	}
	
	public Status getStatus() {
		return status;
	}
	
	public void setVisible(boolean a) {
		isVisible = a;
	}
	
	public boolean isVisible() {
		return isVisible;
	}
	
	public void setContentsVisible(boolean a) {
		for (Entity b : Inventory) {
			b.setVisible(true);
		}
	}
	
	public void inCombat(boolean a) {
		inCombat = a;
	}
	
	public boolean isInCombat() {
		return inCombat;
	}
	
	public boolean checkCombat() {
		return inCombat;
	}
	
	public void equip(String a) {
		Entity result = findItemInInventory(a);
		if (findItemInInventory(a) == null) {
			throw new NullPointerException();
		} else {
			if (result.getClass().getName().equalsIgnoreCase("Weapon")) {
				equipWeapon((Weapon) findItemInInventory(a));
			} else if (result.getClass().getName().equalsIgnoreCase("Armour")) {
				equipArmour((Armour) findItemInInventory(a));
			}
		}		
	}
	
	public void equipWeapon(Weapon a) {
		if (Main_Hand.getName().equalsIgnoreCase("unarmed")) {
			Main_Hand = a;
			Inventory.remove(a);
		} else {
			unequip(Main_Hand.getName());
			Main_Hand = a;
			Inventory.remove(a);
		}
	}
	
	public void equipArmour(Armour a) {
		if (a.getSlot().equalsIgnoreCase("HEAD")) {
			if (Head != null) {
				unequip(Head.getDisplayName());
				Head = a;
			} else {
				Head = a;
			}
		} else if (a.getSlot().equalsIgnoreCase("SHOULDERS")) {
			if (Shoulders != null) {
				unequip(Shoulders.getDisplayName());
				Shoulders = a;
			} else {
				Shoulders = a;
			}
		} else if (a.getSlot().equalsIgnoreCase("CHEST")) {
			if (Chest != null) {
				unequip(Chest.getDisplayName());
				Chest = a;
			} else {
				Chest = a;
			}
		} else if (a.getSlot().equalsIgnoreCase("HANDS")) {
			if (Hands != null) {
				unequip(Hands.getDisplayName());
				Hands = a;
			} else {
				Hands = a;
			}
		} else if (a.getSlot().equalsIgnoreCase("LEGS")) {
			if (Legs != null) {
				unequip(Legs.getDisplayName());
				Legs = a;
			} else {
				Legs = a;
			}
		} else if (a.getSlot().equalsIgnoreCase("FEET")) {
			if (Feet != null) {
				unequip(Feet.getDisplayName());
				Feet = a;
			} else {
				Feet = a;
			}
		}
		modifyEndurance(a.getBonus("Endurance"));
		modifyStrength(a.getBonus("Strength"));
		modifyAgility(a.getBonus("Agility"));
		modifyIntelligence(a.getBonus("Intelligence"));
		modifyWillpower(a.getBonus("Willpower"));
		Inventory.remove(a);
	}
	
	public void unequip(String a) {
		
		if (Main_Hand.getName().contains(a)) {
			Inventory.add(Main_Hand);
			Main_Hand = (Weapon) Inventory.get(0);
		} else if ((Head != null) && Head.getName().contains(a)) {
			modifyEndurance(Head.getBonus("Endurance") * -1);
			modifyStrength(Head.getBonus("Strength") * -1);
			modifyAgility(Head.getBonus("Agility") * -1);
			modifyIntelligence(Head.getBonus("Intelligence") * -1);
			modifyWillpower(Head.getBonus("Willpower") * -1);
			Inventory.add(Head);
			Head = null;
		} else if ((Shoulders != null) && Shoulders.getName().contains(a)) {
			modifyEndurance(Shoulders.getBonus("Endurance") * -1);
			modifyStrength(Shoulders.getBonus("Strength") * -1);
			modifyAgility(Shoulders.getBonus("Agility") * -1);
			modifyIntelligence(Shoulders.getBonus("Intelligence") * -1);
			modifyWillpower(Shoulders.getBonus("Willpower") * -1);
			Inventory.add(Shoulders);
			Shoulders = null;
		} else if ((Chest != null) && Chest.getName().contains(a)) {
			modifyEndurance(Chest.getBonus("Endurance") * -1);
			modifyStrength(Chest.getBonus("Strength") * -1);
			modifyAgility(Chest.getBonus("Agility") * -1);
			modifyIntelligence(Chest.getBonus("Intelligence") * -1);
			modifyWillpower(Chest.getBonus("Willpower") * -1);
			Inventory.add(Chest);
			Chest = null;
		} else if ((Hands != null) && Hands.getName().contains(a)) {
			modifyEndurance(Hands.getBonus("Endurance") * -1);
			modifyStrength(Hands.getBonus("Strength") * -1);
			modifyAgility(Hands.getBonus("Agility") * -1);
			modifyIntelligence(Hands.getBonus("Intelligence") * -1);
			modifyWillpower(Hands.getBonus("Willpower") * -1);
			Inventory.add(Hands);
			Hands = null;
		} else if ((Legs != null) && Legs.getName().contains(a)) {
			modifyEndurance(Legs.getBonus("Endurance") * -1);
			modifyStrength(Legs.getBonus("Strength") * -1);
			modifyAgility(Legs.getBonus("Agility") * -1);
			modifyIntelligence(Legs.getBonus("Intelligence") * -1);
			modifyWillpower(Legs.getBonus("Willpower") * -1);
			Inventory.add(Legs);
			Legs = null;
		} else if ((Feet != null) && Feet.getName().contains(a)) {
			modifyEndurance(Feet.getBonus("Endurance") * -1);
			modifyStrength(Feet.getBonus("Strength") * -1);
			modifyAgility(Feet.getBonus("Agility") * -1);
			modifyIntelligence(Feet.getBonus("Intelligence") * -1);
			modifyWillpower(Feet.getBonus("Willpower") * -1);
			Inventory.add(Feet);
			Feet = null;
		} else {
			gui.getFeedbackWindow().append("");
		}
		
	}
	
	public double getStrengthModifier() {
		double result = ((100.0 - Strength) / 100.0);
		return result;
	}
	

	public Ability getAbility(String a) {
		Ability result = null;
		for (Ability b : Abilities ) {
			if (b.getName().equalsIgnoreCase(a)) {
				result = b;
			}
		}
		return result;
	}
	
	public void modifyCurrentHP(double a) {
		currentHP = currentHP + (int) Math.rint(a);
	}
	
	public boolean isLocked() {
		return false;
	}
	
	public Entity getKey() {
		return null;
	}
	
	public void lock() {
		
	}
	
	public void unlock() {
		
	}
	
	public Weapon get_Main_Hand() {
		return Main_Hand;
	}
	
	public Entity get_Off_Hand() {
		return Off_Hand;
	}	
	
	public void setCurrentOpponent(Character a) {
		currentOpponent = a;
	}
	
	public Character getCurrentOpponent() {
		return currentOpponent;
	}
	
	public void Death() {
		isCorpse = true;
		inCombat = false;
		currentHP = 0;
		actionPoints = 0.0;
	}
	
	public double numActionPoints() {
		return actionPoints;
	}
	
	public void setActionPoints(double a) {
		actionPoints = a;
	}
	
	public void modifyActionPoints(double a) {
		actionPoints = actionPoints + a;
	}
	
	public Consumable findConsumableInInventory(String a) {
		Consumable result = null;
		for (Entity b : Inventory) {
			if (b.getName().contains(a) && b.getClass().getName().toString().equalsIgnoreCase("Consumable")) {
				result = (Consumable) b;
			}
		}
		return result;
	}
	
	public void setCurrentHP(double a) {
		currentHP = (int) Math.rint(a);
	}
	
	public double minActionPoints() {
		double minActionPoints = Abilities.get(0).calcMove_Cost(this);
		return Math.abs(minActionPoints);
	}
	
	public ArrayList<Ability> getAbilities() {
		return Abilities;
	}
	
	public void resetAbilities() {
		for (Ability a : Abilities) {
			a.Reset();
		}
	}
	
	public void startTurn() {
		actionPoints = (actionPoints + (Endurance * 1.5));
	}
	
	public void GenStats() {
		AxeSkill = 1;
		SwordSkill = 1;
		DaggerSkill = 1;
		MaceSkill = 1;
		MaulSkill = 1;
		GreatAxeSkill = 1;
		GreatSwordSkill = 1;
		UnarmedSkill = 1;
		int PointsPool = 35;
		int StatsCounter = 5;
		int minValue = 30;
		int nextInt;
		
		nextInt = random.nextInt(3) + 6;
		
		Endurance = nextInt;
		PointsPool = 35 - Endurance;
		StatsCounter = StatsCounter - 2;
		minValue = StatsCounter * 6;
		
		nextInt = random.nextInt(3) + 6;
		
		while ((PointsPool - nextInt) < minValue) {
			nextInt = random.nextInt(3) + 6;
		}
		Strength = nextInt;
		PointsPool = PointsPool - Strength;
		StatsCounter = StatsCounter - 1;
		minValue = StatsCounter * 6;

		nextInt = random.nextInt(3) + 6;
		
		while ((PointsPool - nextInt) < minValue) {
			nextInt = random.nextInt(3) + 6;
		}
		Intelligence = nextInt;
		PointsPool = PointsPool - Intelligence;
		StatsCounter = StatsCounter - 1;
		minValue = StatsCounter * 6;
		
		nextInt = random.nextInt(3) + 6;
		
		while ((PointsPool - nextInt) < minValue) {
			nextInt = random.nextInt(3) + 6;
		}
		Willpower = nextInt;
		PointsPool = PointsPool - Willpower;
		StatsCounter = StatsCounter - 1;
		minValue = StatsCounter * 6;
		
		nextInt = random.nextInt(3) + 6;
		
		while ((PointsPool - nextInt) < minValue) {
			nextInt = random.nextInt(3) + 6;
		}
		Agility = nextInt;
		PointsPool = PointsPool - Agility;
		StatsCounter = StatsCounter - 1;
		minValue = StatsCounter * 6;
		
		nextInt = random.nextInt(4) + 1;
		
		if (nextInt == 1) {
			Strength = Strength + PointsPool;
		} else if (nextInt == 2) {
			Agility = Agility + PointsPool;
		} else if (nextInt == 3) {
			Endurance = Endurance + PointsPool;
		} else if (nextInt == 4) {
			Intelligence = Intelligence + PointsPool;
		} else if (nextInt == 5) {
			Willpower = Willpower + PointsPool;
		}

	}
	
	public boolean isAsleep() {
		return isAsleep;
	}
	
	public void Sleep(boolean a) {
		isAsleep = a;
		currentHP = maxHP;
	}
	
	public void addGUI(GUI a) {
		gui = a;
	}
	
	public GUI getGUI() {
		return gui;
	}
	
	public void setConvPartner(Character a) {
		conversationPartner = a;
	}
	
	public Character getConvPartner() {
		return conversationPartner;
	}
	
	public void addEffect(StatusEffect a) {
		statuseffects.add(a);
		gui.feedbackWindow.append("You are afflicted by " + a.getName() + "!\n");
		this.modifyStrength(a.getPenalty("Strength"));
		this.modifyAgility(a.getPenalty("Agility"));
		this.modifyEndurance(a.getPenalty("Endurance"));
		this.modifyIntelligence(a.getPenalty("Intelligence"));
		this.modifyWillpower(a.getPenalty("Willpower"));
		
		
		
	}
	
	public void removeEffect(StatusEffect a) {
		statuseffects.remove(a);
		this.modifyStrength(Math.abs(a.getPenalty("Strength")));
		this.modifyAgility(Math.abs(a.getPenalty("Agility")));
		this.modifyEndurance(Math.abs(a.getPenalty("Endurance")));
		this.modifyIntelligence(Math.abs(a.getPenalty("Intelligence")));
		this.modifyWillpower(Math.abs(a.getPenalty("Willpower")));
		gui.feedbackWindow.append(a.getExpiryMsg() + "\n");
	}
	
	public ArrayList<StatusEffect> getEffects() {
		return statuseffects;
	}
	
	public boolean checkCorpse() {
		return isCorpse;
	}
	
	public void addQuest(Quest a) {
		QuestLog.add(a);
	}
	
	public ArrayList<Quest> getQuests() {
		return QuestLog;
	}
	
	public int getSkillPoints() {
		return skillPoints;
	}
	
	public void modifySkillPoints(int a) {
		skillPoints = skillPoints + a;
	}
	
	public void printQuests(JTextArea feedback) {
		if (QuestLog.size() == 0) {
			feedback.append("You currently have no quests");
		} else {
			for (Quest quest : QuestLog) {
				feedback.append(quest.getTitle() + ":\n");
				feedback.append(quest.getGiverName() + " in " + quest.getGiver().getLocation().getDisplayName() + " wants you to " + quest.getMissionType() + " ");
				if (quest.getQuestItems().size() > 1) {	
					for (int i = 0 ; i < (quest.getQuestItems().size() - 1) ; i++) {
						feedback.append(quest.getQuestItems().get(i).getDisplayName() + ", ");
					}
					feedback.append("and " + quest.getQuestItems().get(quest.getQuestItems().size() - 1).getDisplayName() + ".");
				} else {
					feedback.append(quest.getQuestItems().get(0).getDisplayName() + ".\n\n");
				}
			}
		}
	}
	
	public void modifyAxeSkill(int a) {
		AxeSkill = AxeSkill + a;
	}
	
	public void modifySwordSkill(int a) {
		SwordSkill = SwordSkill + a;
	}
	
	public void modifyMaceSkill(int a) {
		MaceSkill = MaceSkill + a;
	}
	
	public void modifyDaggerSkill(int a) {
		DaggerSkill = DaggerSkill + a;
	}
	
	public void modifyGreatAxeSkill(int a) {
		GreatAxeSkill = GreatAxeSkill + a;
	}
	
	public void modifyGreatSwordSkill(int a) {
		GreatSwordSkill = GreatSwordSkill + a;
	}
	
	public void modifyUnarmedSkill(int a) {
		UnarmedSkill = UnarmedSkill + a;
	}
	
	public void modifyMaulSkill(int a) {
		MaulSkill = MaulSkill + a;
	}
	
	public int getAxeSkill() {
		return AxeSkill;
	}
	
	public int getSwordSkill() {
		return SwordSkill;
	}
	
	public int getDaggerSkill() {
		return DaggerSkill;
	}
	
	public int getUnarmedSkill() {
		return UnarmedSkill;
	}
	
	public int getGreatAxeSkill() {
		return GreatAxeSkill;
	}
	
	public int getGreatSwordSkill() {
		return GreatSwordSkill;
	}
	
	public int getMaulSkill() {
		return MaulSkill;
	}
	
	public double ChanceToHit(String a) {
		double baseHit = 70.0;
		if (a.equalsIgnoreCase("fists")) {
			baseHit = baseHit + (15.0 *(UnarmedSkill / 100.0));
			baseHit = baseHit + (15.0 * (Agility / 50.0));
		} else if (a.equalsIgnoreCase("sword")) {
			baseHit = baseHit + (15.0 *(SwordSkill / 100.0));
			baseHit = baseHit + (15.0 * (Agility / 50.0));
		} else if (a.equalsIgnoreCase("dagger")) {
			baseHit = baseHit + (15.0 *(DaggerSkill / 100.0));
			baseHit = baseHit + (15.0 * (Agility / 50.0));
		}  else if (a.equalsIgnoreCase("axe")) {
			baseHit = baseHit + (15.0 *(AxeSkill / 100.0));
			baseHit = baseHit + (15.0 * (Agility / 50.0));
		}
		return baseHit;
	}
	
	public double ChanceToDodge() {
		double baseDodge = 5.0;
		baseDodge = ((baseDodge + (Agility / 2.0)) * calcWeightPenalty());
		return baseDodge;
	}
	
	public double calcFullWeight() {
		return (getArmourWeight() + Main_Hand.getWeight());
	}
	
	public double carriedWeight() {
		double result = calcFullWeight();
		for (Entity a : Inventory) {
			result = result + a.getWeight();
		}
		return result;
	}
	
	public double availableSpace() {
		return maxWeight() - carriedWeight();
	}
	
	public double maxWeight() {
		return (Strength * 4);
	}
	
	public double calcWeightPenalty() {
		return ((100 - (calcFullWeight())) / 100);
	}
	
	public double ChanceToParry(String a) {
		double baseParry = 0.0;
		if (a.equalsIgnoreCase("fists")) {
			baseParry = (UnarmedSkill * (Agility / 100.0));
		} else if (a.equalsIgnoreCase("sword")) {
			baseParry = (SwordSkill * (Agility / 100.0));
		} else if (a.equalsIgnoreCase("dagger")) {
			baseParry = (DaggerSkill * (Agility / 100.0));
		}  else if (a.equalsIgnoreCase("axe")) {
			baseParry = (AxeSkill * (Agility / 100.0));
		}
		if (baseParry < 5.0) {
			baseParry = 5.0;
		}
		return baseParry;
	}
	
	public int parryAmount() {
		int parryAmount = 0;
		parryAmount = Strength * (int) Math.rint(Main_Hand.getWeight());
		return parryAmount;
	}
	
	public double calcArmour() {
		double Armour = 0.0;
		if (Head == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Head.getArmourValue();
		}
		if (Shoulders == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Shoulders.getArmourValue();
		}
		if (Chest == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Chest.getArmourValue();
		}
		if (Hands == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Hands.getArmourValue();
		}
		if (Legs == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Legs.getArmourValue();
		}
		if (Feet == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Feet.getArmourValue();
		}
		
		ArmourRating = Armour;
		return ArmourRating;
	}
	
	public double getArmourWeight() {
		double Armour = 0.0;
		if (Head == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Head.getWeight();
		}
		if (Shoulders == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Shoulders.getWeight();
		}
		if (Chest == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Chest.getWeight();
		}
		if (Hands == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Hands.getWeight();
		}
		if (Legs == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Legs.getWeight();
		}
		if (Feet == null) {
			Armour = Armour + 0.0;
		} else {
			Armour = Armour + Feet.getWeight();
		}
		return Armour;
	}
	
	public Armour getHead() {
		return Head;
	}
	
	public Armour getShoulders() {
		return Shoulders;
	}
	
	public Armour getChest() {
		return Chest;
	}
	
	public Armour getHands() {
		return Hands;
	}
	
	public Armour getLegs() {
		return Legs;
	}
	
	public Armour getFeet() {
		return Feet;
	}
	
	public void modifyEndurance(int a) {
		Endurance = Endurance + a;
		updateMaxHP();
		updateMaxAP();
		if (a != 0) {
		gui.getFeedbackWindow().append("Your Endurance has been");
		if (a > 0) {
			gui.getFeedbackWindow().append(" increased ");
		} else {
			gui.getFeedbackWindow().append(" decreased ");
		}
		gui.getFeedbackWindow().append("by " + Math.abs(a) + ".\n");
		}
	}
	
	public void updateMaxAP() {
		maxAP = Endurance * 4;
	}
	
	public void modifyIntelligence(int a) {
		Intelligence = Intelligence + a;
		if (a != 0) {
		gui.getFeedbackWindow().append("Your Intelligence has been");
		if (a > 0) {
			gui.getFeedbackWindow().append(" increased ");
		} else {
			gui.getFeedbackWindow().append(" decreased ");
		}
		gui.getFeedbackWindow().append("by " + Math.abs(a) + ".\n");
		}
	}
	
	public void modifyWillpower(int a) {
		Willpower = Willpower + a;
		if (a != 0) {
			gui.getFeedbackWindow().append("Your Willpower has been");
			if (a > 0) {
				gui.getFeedbackWindow().append(" increased ");
			} else {
				gui.getFeedbackWindow().append(" decreased ");
			}
			gui.getFeedbackWindow().append("by " + Math.abs(a) + ".\n");
		} else {
			
		}
	}
	
	public void forSale(boolean a) {
		forSale = a;
	}
	
	public boolean isForSale() {
		return forSale;
	}
	
	public void updateMaxHP() {
		if (currentHP == maxHP) {
			maxHP = Endurance * 10;
			if (inCombat == false) {
			currentHP = Endurance * 10;
			}
		} else {
			maxHP = Endurance * 10;
		}
		if (currentHP > maxHP) {
			currentHP = maxHP;
		}
	}
	
	public int ActionsPerformed() {
		return ActionsPerformed;
	}
	
	public void addActionCount() {
		ActionsPerformed++;
	}
	
	public int lastSlept() {
		return lastSlept;
	}
	
	public void setLastSlept(int a) {
		lastSlept = a;
	}
	
	public boolean canSleep() {
		if (((ActionsPerformed - lastSlept) >= 500) || lastSlept == 0) {
			return true;
		} else {
			return false;
		}
	}
	
	public boolean isBed() {
		return isBed;
	}
	
	public void isBed(boolean a) {
		isBed = a;
	}
	
	public double getArmourRating() {
		double result = ((100 - ArmourRating) / 100);
		return result;
	}
}